home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Utilities / Winter Shell 1.0d2 / Source / Libraries / FrameLib / FrameLib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-13  |  8.4 KB  |  315 lines  |  [TEXT/KAHL]

  1. /* handle frames around objects: drawing, resizing, zooming, and
  2.     adjusting the cursor
  3.     94/01/10 aih - upper-cased constants for consistency with other code
  4.     93/11/29 aih - created */
  5.     
  6. #include "DrawLib.h"
  7. #include "MathLib.h"
  8. #include "MemoryLib.h"
  9. #include "RectangleLib.h"
  10. #include "ScrollBarLib.h"
  11. #include "FrameLib.h"
  12. #include "WindowLib.h"
  13.  
  14. Boolean FrameValid(FrameHandle frame)
  15. {
  16.     if (! HandleValidSize(frame, sizeof(FrameType))) return(false);
  17.     if ((**frame).margin < 0) return(false);
  18.     return(true);
  19. }
  20.  
  21. FrameHandle FrameBegin(WindowPtr window, const Rect *bounds, short margin)
  22. {
  23.     FrameHandle frame = NULL;
  24.     RgnHandle rgn = NULL;
  25.     
  26.     require(RectValid(bounds));
  27.     require(margin >= 0);
  28.     TRY {
  29.         frame = HandleBeginClear(sizeof(FrameType));
  30.         (**frame).window = window;
  31.         (**frame).bounds = *bounds;
  32.         (**frame).margin = margin;
  33.         (**frame).flags = FRAME_ANCHOR_RIGHT | FRAME_ANCHOR_BOTTOM;
  34.         WinRegister(window, frame, FrameEventTable());
  35.     } CATCH {
  36.         FrameEnd(frame);
  37.     } ENDTRY;
  38.     ensure(FrameValid(frame));
  39.     return(frame);
  40. }
  41.  
  42. void FrameEnd(FrameHandle frame)
  43. {
  44.     if (frame) {
  45.         WinUnregister((**frame).window, frame);
  46.         HandleEnd(frame);
  47.     }
  48. }
  49.  
  50. FrameFlagsType FrameFlags(FrameHandle frame)
  51. {
  52.     require(FrameValid(frame));
  53.     return((**frame).flags);
  54. }
  55.  
  56. void FrameFlagsSet(FrameHandle frame, FrameFlagsType flags)
  57. {
  58.     require(FrameValid(frame));
  59.     (**frame).flags = flags;
  60. }
  61.  
  62. Boolean FrameFlagTest(FrameHandle frame, FrameFlagsType flags)
  63. {
  64.     return((FrameFlags(frame) & flags) != 0);
  65. }
  66.  
  67. void FrameFlagSet(FrameHandle frame, FrameFlagsType flags, Boolean set)
  68. {
  69.     require(FrameValid(frame));
  70.     if (set)
  71.         (**frame).flags |= flags;
  72.     else
  73.         (**frame).flags &= ~flags;
  74.     ensure(FrameFlagTest(frame, flags) == set);
  75. }
  76.  
  77. void FrameActivate(FrameHandle frame, Boolean active)
  78. {
  79.     if (FrameFlagTest(frame, FRAME_ACTIVE) != active) {
  80.         FrameFlagSet(frame, FRAME_ACTIVE, active);
  81.         if (FrameFlagTest(frame, FRAME_LIST))
  82.             FrameDraw(frame);
  83.     }
  84. }
  85.  
  86. void FrameFocus(FrameHandle frame, Boolean focus)
  87. {
  88.     if (FrameFlagTest(frame, FRAME_FOCUS) != focus) {
  89.         FrameFlagSet(frame, FRAME_FOCUS, focus);
  90.         if (FrameFlagTest(frame, FRAME_LIST))
  91.             FrameDraw(frame);
  92.     }
  93. }
  94.  
  95. Boolean FrameHilite(FrameHandle frame)
  96. {
  97.     if (((**frame).flags & FRAME_ACTIVE) == 0) return(false);
  98.     if (((**frame).flags & FRAME_KEEP_INACTIVE) != 0) return(false);
  99.     if (((**frame).flags & FRAME_KEEP_ACTIVE) != 0) return(true);
  100.     return(((**frame).flags & FRAME_FOCUS) != 0);
  101. }
  102.  
  103. void FrameCursor(FrameHandle frame, short cursor)
  104. {
  105.     require(FrameValid(frame));
  106.     (**frame).cursor = cursor;
  107. }
  108.  
  109. void FrameContent(FrameHandle frame, Rect *content)
  110. {
  111.     require(FrameValid(frame));
  112.     *content = (**frame).bounds;
  113.     if (((**frame).flags & FRAME_LIST) != 0)
  114.         InsetRect(content, FRAME_FOCUS_SIZE, FRAME_FOCUS_SIZE);
  115.     if (((**frame).flags & FRAME_VSCROLL) != 0) content->right -= SBAR_WIDTH - 1;
  116.     if (((**frame).flags & FRAME_HSCROLL) != 0) content->bottom -= SBAR_WIDTH - 1;
  117.     InsetRect(content, FRAME_WIDTH + (**frame).margin,
  118.                              FRAME_WIDTH + (**frame).margin);
  119.     ensure(RectValid(content));
  120. }
  121.  
  122. void FrameBounds(FrameHandle frame, Rect *bounds)
  123. {
  124.     require(FrameValid(frame));
  125.     *bounds = (**frame).bounds;
  126.     ensure(RectValid(bounds));
  127. }
  128.  
  129. short FrameMinWidth(FrameHandle frame)
  130. {
  131.     require(FrameValid(frame));
  132.     return
  133.         2 * FRAME_WIDTH +
  134.         2 * (**frame).margin +
  135.         2 * (((**frame).flags & FRAME_LIST) != 0 ? FRAME_FOCUS_SIZE : 0) +
  136.         SBarMinWidth(((**frame).flags & FRAME_HSCROLL) != 0,
  137.                          ((**frame).flags & FRAME_VSCROLL) != 0);
  138. }
  139.  
  140. short FrameMinHeight(FrameHandle frame)
  141. {
  142.     require(FrameValid(frame));
  143.     return
  144.         2 * FRAME_WIDTH +
  145.         2 * (**frame).margin +
  146.         2 * (((**frame).flags & FRAME_LIST) != 0 ? FRAME_FOCUS_SIZE : 0) +
  147.         SBarMinHeight(((**frame).flags & FRAME_HSCROLL) != 0,
  148.                           ((**frame).flags & FRAME_VSCROLL) != 0);
  149. }
  150.  
  151. Boolean FrameWithin(FrameHandle frame, Point where)
  152. {
  153.     Rect bounds;
  154.     FrameBounds(frame, &bounds);
  155.     if (((**frame).flags & FRAME_LIST) != 0)
  156.         InsetRect(&bounds, FRAME_FOCUS_SIZE, FRAME_FOCUS_SIZE);
  157.     return(PtInRect(where, &bounds));
  158. }
  159.  
  160. static void FrameDoDraw(FrameHandle frame, RgnHandle border1, RgnHandle border2,
  161.     RgnHandle border3)
  162. {
  163.     Rect content, bounds;
  164.     GrafPtr port = NULL;
  165.     
  166.     require(FrameValid(frame));
  167.     GetPort(&port);
  168.     SetPort((**frame).window);
  169.     FrameContent(frame, &content);
  170.     InsetRect(&content,    -(FRAME_WIDTH + (**frame).margin),
  171.                                 -(FRAME_WIDTH + (**frame).margin));
  172.     if (border1)
  173.         BorderRgn(&content, FRAME_WIDTH, (**frame).margin, false, border1);
  174.     else
  175.         BorderDraw(&content, FRAME_WIDTH, (**frame).margin, true);
  176.     FrameBounds(frame, &bounds);
  177.     if (((**frame).flags & FRAME_LIST) != 0) {
  178.         if (border2)
  179.             BorderRgn(&bounds, 2, 1, false, border2);
  180.         else
  181.             BorderDraw(&bounds, 2, 1, FrameHilite(frame));
  182.         InsetRect(&bounds, FRAME_FOCUS_SIZE, FRAME_FOCUS_SIZE);
  183.         if (((**frame).flags & FRAME_HSCROLL) != 0 ||
  184.              ((**frame).flags & FRAME_VSCROLL) != 0)
  185.         {
  186.             /* when a list is not active, the List Manager doesn't draw
  187.                 a frame around the scroll bars, so we draw it here */
  188.             if (border3)
  189.                 BorderRgn(&bounds, 1, 0, false, border3);
  190.             else
  191.                 BorderDraw(&bounds, 1, 0, true);
  192.         }
  193.     }
  194.     SetPort(port);
  195. }
  196.  
  197. void FrameDraw(FrameHandle frame)
  198. {
  199.     FrameDoDraw(frame, NULL, NULL, NULL);
  200. }
  201.  
  202. void FrameGrow(FrameHandle frame, Rect *size)
  203. {
  204.     Rect bounds, port;
  205.     
  206.     require(FrameValid(frame));
  207.     FrameBounds(frame, &bounds);
  208.     WinPortRect((**frame).window, &port);
  209.     if (((**frame).flags & FRAME_ANCHOR_RIGHT) != 0)
  210.         size->left = RectWidth(&port) - RectWidth(&bounds) + FrameMinWidth(frame);
  211.     if (((**frame).flags & FRAME_ANCHOR_BOTTOM) != 0)
  212.         size->top = RectHeight(&port) - RectHeight(&bounds) + FrameMinHeight(frame);
  213. }
  214.  
  215. void FrameZoom(FrameHandle frame, short *width, short *height)
  216. {
  217.     Rect bounds, content, port;
  218.     Point border;
  219.  
  220.     require(FrameValid(frame));
  221.     FrameContent(frame, &content);
  222.     FrameBounds(frame, &bounds);
  223.     WinPortRect((**frame).window, &port);
  224.     if (((**frame).flags & FRAME_ANCHOR_RIGHT) == 0)
  225.         *width = RectWidth(&content);
  226.     if (((**frame).flags & FRAME_ANCHOR_BOTTOM) == 0)
  227.         *height = RectHeight(&content);
  228.     border.h = RectWidth(&bounds) - RectWidth(&content);
  229.     border.v = RectHeight(&bounds) - RectHeight(&content);
  230.     *width = min(SHRT_MAX, max((long) *width + border.h, FrameMinWidth(frame)) +
  231.                     RectWidth(&port) - RectWidth(&bounds));
  232.     *height = min(SHRT_MAX, max((long) *height + border.v, FrameMinHeight(frame)) +
  233.                     RectHeight(&port) - RectHeight(&bounds));
  234. }
  235.  
  236. void FrameResize(FrameHandle frame, short dh, short dv)
  237. {
  238.     #define NBRDR (3)
  239.     #define NRGN (2 * NBRDR)
  240.     RgnHandle rgn[NRGN];
  241.     short i = 0;
  242.     Rect r1, r2;
  243.     GrafPtr port = NULL;
  244.  
  245.     require(FrameValid(frame));
  246.     for (i = 0; i < NRGN; i++)
  247.         rgn[i] = NULL;
  248.     TRY {
  249.         if (((**frame).flags & FRAME_ANCHOR_RIGHT) == 0) dh = 0;
  250.         if (((**frame).flags & FRAME_ANCHOR_BOTTOM) == 0) dv = 0;
  251.         if (dh || dv) {
  252.             for (i = 0; i < NRGN; i++)
  253.                 rgn[i] = BeginRgn();
  254.             GetPort(&port);
  255.             SetPort((**frame).window);
  256.             FrameDoDraw(frame, rgn[0], rgn[1], rgn[2]);
  257.             r1 = (**frame).bounds;
  258.             check(RectWidth(&r1) + dh >= FrameMinWidth(frame));
  259.             check(RectHeight(&r1) + dv >= FrameMinHeight(frame));
  260.             (**frame).bounds.bottom += dv;
  261.             (**frame).bounds.right += dh;
  262.             r2 = (**frame).bounds;
  263.             InvalXorRect(&r1, &r2);
  264.             FrameDoDraw(frame, rgn[3], rgn[4], rgn[5]);
  265.             //debug_note
  266.             for (i = 0; i < NRGN; i++) {
  267.                 EraseRgn(rgn[i]);
  268.                 InvalRgn(rgn[i]);
  269.             }
  270.             //for (i = 0; i < NBRDR; i++)
  271.             //    InvalXorRgn(rgn[i], rgn[i + NBRDR]);
  272.         }
  273.     } CLEANUP {
  274.         for (i = 0; i < NRGN; i++) EndRgn(rgn[i]);
  275.         if (port) SetPort(port);
  276.     } ENDTRY;
  277. }
  278.  
  279. Boolean FrameAdjustCursor(FrameHandle frame, Point where, RgnHandle cursorRgn)
  280. {
  281.     GrafPtr port;
  282.     Rect contentRect;
  283.     Boolean result = false;
  284.     RgnHandle contentRgn, visRgn;
  285.     
  286.     require(FrameValid(frame));
  287.     require(ValidateRgn(cursorRgn));
  288.     /* If the cursor is within the frame's content rectangle then set the cursor
  289.         region to the content region and return true. Otherwise, subtract the
  290.         content region from the cursor region and return false. */
  291.     if ((**frame).cursor) {
  292.         GetPort(&port);
  293.         SetPort((**frame).window);
  294.         contentRgn = BeginRgn();
  295.         visRgn = BeginRgn();
  296.         FrameContent(frame, &contentRect);
  297.         RectPortToGlobal(&contentRect, (**frame).window);
  298.         RectRgn(contentRgn, &contentRect);
  299.         CopyRgn((**frame).window->visRgn, visRgn);
  300.         LocalToGlobalRgn(visRgn);
  301.         SectRgn(visRgn, contentRgn, contentRgn);
  302.         if (PtInRgn(where, contentRgn)) {
  303.             CopyRgn(contentRgn, cursorRgn);
  304.             DrawCursor((**frame).cursor);
  305.             result = true;
  306.         }
  307.         else
  308.             DiffRgn(cursorRgn, contentRgn, cursorRgn);        
  309.         EndRgn(contentRgn);
  310.         EndRgn(visRgn);
  311.         SetPort(port);
  312.     }
  313.     return(result);    
  314. }
  315.